SDUI
SDUI는 Server Driven UI의 약자로, 화면을 어떤 UI로 구성할지를 서버가 결정하고, 클라이언트는 서버가 내려준 정의를 해석하여 화면을 그리는 방식을 의미한다.
기존 방식에서는 화면의 구조와 배치가 클라이언트 코드에 고정되어 있고, 서버는 그 화면을 채울 데이터만 내려준다.
반면 SDUI에서는 어떤 컴포넌트를, 어떤 순서로, 어떤 값으로 보여줄지를 서버 응답이 함께 정의한다.


기존 방식의 한계
앞서 본 광고나 실험(AB 테스트)처럼 기간·위치·대상에 따라 다른 View를 노출해야 하는 상황을 생각해보자.
일반적인 클라이언트 중심 UI에서는 화면 구조가 앱 코드에 하드코딩된다.
예를 들어 목록 화면이 다음과 같이 구성되어 있다고 하자.
Column {
Header(data.header)
ContentList(data.items)
Footer(data.footer)
}
이 코드에서 서버는 각 영역에 들어갈 데이터만 내려줄 뿐, 화면의 구조는 앱에 고정되어 있다.
이 상태에서 “특정 기간 동안, 목록 중간에, 특정 사용자에게만 광고 배너를 끼워 넣고 싶다”는 요구가 생기면 클라이언트 코드를 수정하고 다시 배포해야 한다.
문제는 모바일의 특성상 다음과 같은 제약이 따른다는 점이다.
- 화면 구성을 바꿀 때마다 앱 배포가 필요하다.
- 앱 스토어 심사 기간만큼 반영이 지연된다.
- 사용자가 앱을 업데이트하지 않으면 최신 화면을 볼 수 없다.
즉, 광고나 실험처럼 짧은 주기로 바뀌고, 조건에 따라 다르게 노출되어야 하는 화면을 클라이언트 코드만으로 대응하기는 어렵다.
이러한 문제를 해결하기 위해, 화면의 구성 자체를 서버가 제어하는 SDUI가 등장하게 되었다.
SDUI의 핵심 아이디어
SDUI의 핵심은 화면을 데이터로 표현하는 것이다.
즉, “이 화면은 제목·설명 영역과 이미지가 붙은 영역으로 구성된다”라는 구조 자체를 서버 응답(JSON)으로 표현한다.
이렇게 하면 광고나 실험용 컴포넌트를 원하는 위치에, 원하는 기간 동안 서버 응답에 끼워 넣기만 하면 되므로, 앱 배포 없이 화면을 유연하게 바꿀 수 있다.
클라이언트는 화면을 직접 정의하지 않고, 서버가 내려준 UI 정의를 순회하며 대응되는 컴포넌트를 그린다.
flowchart LR
Server["서버"]
Response["UI 정의 (JSON)"]
Client["클라이언트"]
Screen["화면"]
Server -->|UI 구조 + 데이터 생성| Response
Response -->|응답 전달| Client
Client -->|정의 해석 후 렌더링| Screen
- 서버가 화면을 구성하는 UI 정의를 생성한다.
- 서버는 UI 정의를 JSON 형태의 응답으로 내려준다.
- 클라이언트는 응답을 파싱하여 각 컴포넌트를 렌더링한다.
즉, 서버는 “무엇을 보여줄지”를 결정하고, 클라이언트는 “어떻게 그릴지”만 담당한다.
구성 요소
SDUI 응답은 화면을 구성하는 컴포넌트들의 목록으로 이루어진다.
각 컴포넌트는 일반적으로 다음과 같은 요소로 구성된다.
- viewType (컴포넌트 종류)
- 화면을 구성하는 UI 조각의 종류를 나타낸다.
- 클라이언트는 이 값을 기준으로 어떤 UI를 그릴지 결정한다.
TitleDescriptionViewType처럼 구성 요소와 배치를 이름에 담아 표현하기도 한다.
- content (데이터)
- 해당 컴포넌트가 실제로 표시할 값이다.
- 제목, 설명, 이미지 정보 등이 포함되며
viewType마다 형태가 다르다.
- image / icon (시각 요소)
- 이미지 URL뿐 아니라 크기(
size), 배경색(bgColor) 등 표현에 필요한 속성을 함께 정의한다.
- 이미지 URL뿐 아니라 크기(
- action (액션)
- 컴포넌트에서 발생하는 사용자 상호작용을 정의한다.
- 화면 이동(
navigate), 토스트(showToast), 스낵바(showSnackBar) 등이 해당된다.
여기서 주목할 점은 viewType의 작명 방식이다.
StartImageTitleDescriptionActionIconType처럼 어떤 요소가 어떤 위치에 배치되는지를 이름에 그대로 담으면, 별도의 레이아웃 필드 없이도 서버와 클라이언트가 화면 구조를 공유할 수 있다. (자세한 내용은 아래 API 응답 설계에서 다룬다.)
서버와 클라이언트의 역할
SDUI에서 서버와 클라이언트의 책임은 명확하게 나뉜다.
| 구분 | 책임 |
|---|---|
| 서버 | 어떤 컴포넌트를, 어떤 순서로, 어떤 데이터와 액션으로 보여줄지 결정 |
| 클라이언트 | viewType에 대응하는 UI를 렌더링하고, 액션을 실행 |
여기서 중요한 점은 클라이언트가 컴포넌트의 종류(viewType)를 미리 알고 있어야 한다는 것이다.
서버는 화면의 “구성”을 바꿀 수 있지만, 클라이언트가 해석할 수 없는 새로운 viewType을 만들 수는 없다.
즉, 서버는 이미 정의된 컴포넌트들을 조합하여 화면을 구성한다.
flowchart LR
subgraph Server["서버"]
direction TB
S1["컴포넌트 조합"]
S2["content 매핑"]
S3["action 정의"]
end
subgraph Client["클라이언트"]
direction TB
C1["viewType 매칭"]
C2["컴포넌트 렌더링"]
C3["action 처리"]
end
Server -->|UI 정의 JSON| Client
API 응답 설계
SDUI에서 가장 중요한 것은 화면을 표현하는 응답(스키마) 설계이다.
응답은 보통 컴포넌트들의 목록으로 구성되며, 각 컴포넌트는 viewType과 content를 가진다.
예를 들어 다음과 같은 응답을 설계할 수 있다.
{
"sduiComponents": [
{
"viewType": "TitleDescriptionViewType",
"content": {
"titleText": "Title",
"descriptionText": "This is Description Text for type1"
}
},
{
"viewType": "TitleDescriptionEndImageViewType",
"content": {
"titleText": "Title",
"descriptionText": "This is Description Text for type2",
"descriptionTextV2": {
"text": [
{ "text": "This is" },
{ "text": "Description Text", "style": "bold" }
]
},
"image": {
"imgUrl": "https://aiswmaestro.org/2x/smile-icon.png",
"size": { "width": 16, "height": 16 },
"bgColor": "#232323"
}
}
},
{
"viewType": "StartImageTitleDescriptionActionIconType",
"content": {
"titleText": "Title",
"descriptionText": "This is Description Text for type2",
"image": {
"imgUrl": "https://aiswmaestro.org/2x/smile-icon.png",
"size": { "width": 20, "height": 20 },
"bgColor": "#232323"
},
"actionIcon": {
"imgUrl": "https://aiswmaestro.org/2x/smile-icon.png",
"size": { "width": 20, "height": 20 },
"action": {
"navigateLink": "https://aiswmaestro.org/page2",
"actionType": "navigate"
}
}
}
}
]
}
이 응답을 해석해보면 세 개의 컴포넌트가 위에서 아래로 순서대로 그려진다.
TitleDescriptionViewType— 제목과 설명만 있는 가장 단순한 형태TitleDescriptionEndImageViewType— 제목/설명의 오른쪽 끝(End)에 아이콘 이미지가 붙는 형태StartImageTitleDescriptionActionIconType— 왼쪽(Start)에 이미지, 오른쪽에 액션 아이콘이 붙는 형태
만약 서버가 sduiComponents 배열의 순서를 바꾸거나, 노출 대상·기간에 따라 컴포넌트를 추가/삭제하면 앱 배포 없이 화면 구성이 바뀐다.
viewType — 화면 구조를 담은 이름
이 스키마에서 viewType은 단순한 종류 구분을 넘어 레이아웃 자체를 이름으로 표현한다.
StartImage...→ 이미지가 앞(Start)에 위치...EndImage...→ 이미지가 뒤(End)에 위치...ActionIcon...→ 상호작용 가능한 아이콘 포함
덕분에 별도의 레이아웃 필드 없이도, viewType 이름만으로 클라이언트가 어떤 구조를 그려야 하는지 알 수 있다.
content — viewType마다 달라지는 데이터
content는 viewType에 따라 형태가 달라진다.
- titleText / descriptionText — 기본 텍스트 값이다.
- descriptionTextV2 — 부분 스타일링을 위한 확장 필드이다.
text배열의 각 조각(span)마다style(예:bold)을 지정할 수 있어, 한 문장 안에서 일부만 강조할 수 있다.
- image — 이미지 URL뿐 아니라
size,bgColor등 표현 속성을 함께 정의한다. - actionIcon — 이미지에
action이 결합된 형태이다.actionType으로 동작을 구분한다. (navigate,showToast,showSnackBar등)navigate인 경우navigateLink로 이동할 위치를 지정한다.
여기서 descriptionText와 descriptionTextV2가 함께 존재하는 점에 주목할 수 있다.
descriptionTextV2를 해석하지 못하는 구버전 클라이언트는 기존 descriptionText를 그대로 사용하고,
신버전 클라이언트는 descriptionTextV2로 더 풍부한 표현을 그린다.
이렇게 하위 호환을 고려한 필드 확장(V2) 방식으로 스키마를 점진적으로 발전시킬 수 있다.
필드 설계 원칙
응답 스키마를 설계할 때 다음을 고려한다.
- viewType은 클라이언트와 서버가 공유하는 약속이다.
- 클라이언트가 이미 구현해 둔 값만 사용할 수 있다.
- content는 viewType마다 형태가 다르다.
viewType에 따라 어떤content구조가 오는지 명세가 필요하다.
- 클라이언트가 모르는 viewType은 무시할 수 있어야 한다.
- 서버가 새 컴포넌트를 추가해도 구버전 앱이 깨지지 않도록 한다.
여기까지 정리하면, SDUI에서 API 응답을 설계한다는 것은 결국 화면을 컴포넌트 단위로 쪼개고, 각 컴포넌트를 viewType과 content로 표현하는 규칙을 서버와 클라이언트가 함께 약속하는 일이라고 할 수 있다.